package hamaster.jpbc.mgr;

import static hamaster.jpbc.mgr.Messages.getString;
import hamaster.jpbc.Main;
import hamaster.jpbc.crypt.CryptIO;
import hamaster.jpbc.crypt.impl.IBENativeCryptIOImpl;
import hamaster.jpbc.exception.CryptException;
import hamaster.jpbc.gui.callback.AsynchronousCallback;
import hamaster.jpbc.pbc.PBC;
import hamaster.jpbc.pbc.PBCDriver;
import hamaster.jpbc.util.Hash;
import it.unisa.dia.gas.jpbc.Element;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Properties;

import javax.swing.JOptionPane;

public class AsymmetricEncryptManager extends SymmetricEncryptManager {

	public AsymmetricEncryptManager(AsynchronousCallback callback,
			String crypto, File plain, String alice, File cipher) {
		super(callback, crypto, plain, alice, cipher);
	}

	@Override
	public void run() {
		if (!"IBC".equalsIgnoreCase(crypto)) {
			super.run();
			return;
		}
		PBC pbc = PBC.instance();
		Element receiver = pbc.getPairing().getZr().newElement();
		receiver.setFromBytes(Hash.sha1(alice));
		String cipherName = cipher.getName().substring(0, cipher.getName().length() - 4) + ".data";
		CryptIO io = new IBENativeCryptIOImpl(new File(cipher.getParent(), cipherName).getAbsolutePath(), receiver, Main.publicParameter());
		io.setProgressListener(callback);
		Properties metadata = new Properties();
		metadata.setProperty(SYMMETRIC_KEY, PBCDriver.hex("IBC".getBytes()));
		try {
			metadata.setProperty(PLAIN_FILE_NAME, PBCDriver.hex(plain.getName().getBytes("UTF-8")));
			metadata.setProperty(CIPHER_NAME_KEY, PBCDriver.hex(cipherName.getBytes("UTF-8")));
		} catch (UnsupportedEncodingException e) {
			metadata.setProperty(PLAIN_FILE_NAME, PBCDriver.hex(plain.getName().getBytes()));
			metadata.setProperty(CIPHER_NAME_KEY, PBCDriver.hex(cipherName.getBytes()));
		}
		metadata.setProperty(PLAIN_FILE_LENGTH, plain.length() + new String());
		Thread signd = new Thread(new SignatureThread(this, plain, cipher.getParentFile(), ibcID, metadata, cipher.getName(), sign));
		signd.start();
		try {
			io.encrypt(plain, null);
		} catch (IOException e) {
			callback.message(getString("SymmetricEncryptManager.cannotWriteCipher"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$
			return;
		} catch (CryptException e) {
			callback.message(getString("SymmetricEncryptManager.errorEncrypting"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$
			return;
		}
		callback.message(getString("SymmetricEncryptManager.waitingForSign"), AsynchronousCallback.TITLE_MESSAGE); //$NON-NLS-1$
		for (;;) {
			if (complete)
				break;
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
			}
		}
		callback.message("IBC", AsynchronousCallback.TITLE_MESSAGE); //$NON-NLS-1$
		if (error) {
			callback.message(getString("SymmetricEncryptManager.errorSaveMeta"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$
		} else {
			callback.message(getString("SymmetricEncryptManager.finished"), JOptionPane.INFORMATION_MESSAGE); //$NON-NLS-1$
		}
	}
}
